home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CCARD15.ZIP / SOURCE.ZIP / CARD.C next >
Encoding:
C/C++ Source or Header  |  1996-11-23  |  29.4 KB  |  701 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. #include <string.h>
  5. #include <conio.h>
  6. #include "allegro.h"
  7. #include "card.h"
  8. BITMAP *buffer, *tempa, *treepic, *transparence;
  9. COMPILED_SPRITE *rot[46][42];
  10. int sintbl[42] = {
  11. 0, -5, -11, -17, -22, -27, -31, -34, -37, -39, -39, -39, -39, -37, -34, -31, -27, -22, -17, -11, -5, 0, 5, 11, 17, 22, 27, 31, 34, 37, 39, 39, 39, 39, 37, 34, 31, 27, 22, 17, 11, 5, 
  12. };
  13. int costbl3[210] = {
  14. 112, 111, 111, 111, 111, 111, 111, 110, 110, 110, 109, 109, 108, 107, 107, 106, 105, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 94, 93, 92, 91, 89, 88, 87, 85, 84, 82, 81, 79, 78, 76, 75, 74, 72, 71, 69, 67, 65, 64, 63, 61, 59, 57, 56, 54, 52, 50, 49, 48, 46, 44, 42, 41, 39, 38, 37, 35, 34, 32, 31, 29, 28, 26, 25, 24, 22, 21, 20, 19, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 24, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 39, 41, 42, 44, 46, 48, 49, 50, 52, 54, 56, 57, 59, 61, 63, 64, 65, 67, 69, 71, 72, 74, 75, 76, 78, 79, 81, 82, 84, 85, 87, 88, 89, 91, 92, 93, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 110, 110, 111, 111, 111, 111, 111, 111
  15. };
  16. char costbl2[280] = {
  17. 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 49, 49, 49, 49, 48, 48, 48, 48, 48, 47, 47, 47, 47, 46, 46, 46, 46, 46, 45, 45, 45, 45, 44, 44, 44, 44, 44, 43, 43, 43, 43, 42, 42, 42, 42, 42, 41, 41, 41, 40, 40, 40, 40, 39, 39, 39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 35, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 28, 28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 25, 25, 25, 25, 25, 24, 24, 24, 24, 23, 23, 23, 23, 23, 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 20, 19, 19, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 17, 17, 16, 16,
  18. 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11
  19. };
  20. char costbl[536] = {
  21. 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 58, 58, 58, 57, 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 51, 51, 50, 50, 49, 48, 48, 47, 46, 46, 45, 44, 44, 43, 42, 42, 41, 40, 39, 39, 38, 37, 36, 36, 35, 34, 33, 33, 32, 31, 30, 30, 29, 28, 27, 27, 26, 25, 24, 24, 23, 22, 21, 21, 20, 19, 19, 18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21, 21, 22, 23, 24, 24, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39, 39, 40, 41, 42, 42, 43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 50, 51, 51, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 57, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 60, 60,
  22. 60, 60, 59, 59, 58, 58, 58, 57, 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 49, 49, 48, 47, 47, 46, 45, 45, 44, 43, 43, 42, 41, 40, 39, 39, 38, 37, 36, 36, 35, 34, 33, 33, 32, 31, 30, 30, 29, 28, 27, 27, 26, 25, 24, 24, 23, 22, 21, 21, 20, 19, 19, 18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23, 23, 24, 25, 25, 26, 27, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39, 39, 40, 41, 42, 42, 43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 50, 51, 51, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 57, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 58, 58, 58, 57, 57, 56, 56
  23. };
  24. volatile int game_time = 1; long frame_count = 8; double speed = 2;
  25. unsigned char tree=0,end=0,song=1,col[100],*colptr,message[1024],temptbl[281];
  26. double tmov1=0,tmov2=0,tmov3=0,tmov4=0;
  27. signed char s_pos=5,s_row=0,s_col=0,p_col=0,m_col=0,s_rows;
  28. signed char songpos,picpos,bgpos,textpos,dots=0,font_change=0;
  29. char song_name[16],pic_name[16];int offsets[14],xpos[100],*xposptr;
  30. MIDI *the_song;
  31. BITMAP *intro_pic;DATAFILE *datafile; RGB pal[242][256],picpal[256];
  32. void game_timer()
  33. {                
  34.    game_time++;  
  35. }
  36. insert_chara(char *strp, int pos, char ins)
  37. {
  38.    int w;
  39.    for(w=strlen(strp);w>pos;w--) strp[w]=strp[w-1];
  40.    strp[pos]=ins;
  41. }
  42. delete_chara(char *strp, int pos)
  43. {
  44.    int w;
  45.    for(w=pos;w<strlen(strp);w++) strp[w]=strp[w+1];
  46.    strp[strlen(strp)]=0;
  47. }
  48. void main(int argc, char *argv[])
  49. {
  50.    int x, z=0, zo=0, zp=0, zq=0; double zd=0; unsigned char *c, *c2, y;
  51.    char buf[5];
  52.    buffer = create_bitmap(325,135); clear(buffer);
  53.    for(x=1;x<argc;x++) {
  54.       if(strstr(argv[x], "-f") || strstr(argv[x], "-F") ||
  55.          strstr(argv[x], "/f") || strstr(argv[x], "/F")) font_change = 1;
  56.       if(strcmp(argv[x], "-?") || strstr(argv[x], "/?") ||
  57.          strstr(argv[x], "-h") || strstr(argv[x], "-H") ||
  58.          strstr(argv[x], "/h") || strstr(argv[x], "/H") ||
  59.          strstr(argv[x], "-s") || strstr(argv[x], "-S") ||
  60.          strstr(argv[x], "/s") || strstr(argv[x], "/S")) setup_mode();
  61.    }
  62.    c2=message; init();
  63.    while(!key[KEY_ESC]) {
  64.       if(end) textpos = 0; if(!textpos) drawplasma(); else clear(buffer);
  65.       if(!end) {
  66.          if(z-zo>=18) {
  67.             *c2++; zo=z;
  68.             if(key[KEY_F]) {
  69.                sprintf(buf, "%d=%d", 4*frame_count/game_time, (int)(40*frame_count/game_time)%10);
  70.                draw_word(1,1,buf,1);draw_word(1,1,buf,2);
  71.             }
  72.          }
  73.          c = c2;
  74.          for(x=(20-(z-zo));x<300;x+=18) {
  75.             if(*c < 46) draw_compiled_sprite(buffer, rot[*c][((x*3+z)%840)/20], x, costbl3[((x*3+z)%840)/4]);
  76.             *c++;
  77.          }
  78.          if(*c==128) {tree = 1; end = 1;}
  79.       }
  80.       if(textpos) drawplasma();
  81.       if(z-zq>=2) {
  82.          zq=z; xposptr = xpos; colptr = col;
  83.          for(x=0;x<100;x++) {
  84.             if(*xposptr<320 && tempa->line[x*2+1][*xposptr]<14) _putpixel(screen,*xposptr,x*2+1,0);
  85.             *xposptr -= ((*colptr/2)-2);
  86.             if(*xposptr < 0) {
  87.                *xposptr = 320+random()%160;
  88.                *colptr = random()%6+7;
  89.             }
  90.             if(*xposptr<320 && tempa->line[x*2+1][*xposptr]<14)
  91.                _putpixel(screen,*xposptr,x*2+1,*colptr);
  92.             xposptr++;colptr++;
  93.          }
  94.          if(key[KEY_T]) {tree = 1;screen->vtable->blit_from_memory(datafile[TREE].dat, treepic, 0, 0, 0, 0, 280, 125);}
  95.          else if(key[KEY_C]) {tree = 1;screen->vtable->blit_from_memory(datafile[CROSS].dat, treepic, 0, 0, 0, 0, 280, 125);}
  96.          else if(key[KEY_N]) tree = 0;
  97.       }
  98.       if(z-zp>=4) {zp=z; _vga_set_pallete_range(pal[z/4%242], 14, 255, 1);}
  99.       screen->vtable->blit_from_memory(buffer, screen, 20, 5, 20, 60, 280, 125);
  100.       zd+=speed;z = (int)zd;frame_count++;
  101.       speed = ((double)10*game_time)/(double)frame_count;
  102.       if(frame_count>=10000) {frame_count /= 4; game_time /= 4;}
  103.    }
  104.    set_pallete_range(pal[z/4%242], 0, 255, 1); fade_out(2); clear(screen);
  105.    draw_word(10, 90,"merry christmas",0);
  106.    fade_in(datafile[PALLETE_001].dat, 2);
  107.    rest(2000); fade_out(2); allegro_exit();
  108.    printf("---------------------------------------------------\n");
  109.    printf("This programme was brought to you by Michael Bevin.\n");
  110.    printf("You may use it as an 'electronic christmas card' by\n");
  111.    printf("editing the message in setup (card -s) provided you\n");
  112.    printf("do not edit the original program files. Feel free 2\n");
  113.    printf("e-mail me at michael.bevin@stonebow.otago.ac.nz if \n");
  114.    printf("u like it or want to know how I made it etc.       \n");
  115.    printf("---------------------------------------------------\n");
  116.    clear_keybuf(); 
  117.    exit(0);
  118. }
  119. drawplasma()
  120. {
  121.   unsigned char x, *p1, *p3, *p6, *p7, *p8, mov;
  122.   register unsigned char tmov, *p4, *p2;
  123.   unsigned long address;
  124.   tmov1+=((double)(random()%2-4)*speed/2.5);
  125.   tmov2-=((double)(random()%3)*speed/2.5);
  126.   tmov3+=((double)(random()%2+4)*speed/2.5);
  127.   tmov4-=((double)(random()%3)*speed/2.5);
  128.   p2 = temptbl; if(tree) p3 = &treepic->line[0][0];
  129.   p4 = &buffer->line[5][20] - 1; p6 = costbl2;
  130.   mov=(int)tmov2; p7 = &costbl[mov];
  131.   mov=(int)tmov1; p8 = &costbl[mov];
  132.   while(*p2) *p2++=*p6++ + *p7++ + *p8++;
  133.   p6 = costbl2; p2 = temptbl;
  134.   mov=(int)tmov3; p7 = &costbl[mov];
  135.   mov=(int)tmov4; p8 = &costbl[mov];
  136.   if(!textpos) address = bmp_write_line(buffer, 5)+20;
  137.   for(x=0;x<125;x++) {
  138.     tmov=*p6++ + *p7++ + *p8++;
  139.     if(!textpos) {
  140.        _movedatal(_my_ds(),(unsigned)p2,buffer->seg,address,71);
  141.        address+=325;
  142.     }
  143.     else p2 = temptbl;
  144.     if(tree && textpos)
  145.       {while(*p2){*(++p4)+=*p2++ + *p3++ +tmov;if(*p4<tmov) *p4+=14;} p4+=45;}
  146.     else if(textpos)
  147.       {while(*p2){*(++p4)+=*p2++ +tmov;if(*p4<tmov) *p4+=14;} p4+=45;}
  148.     else if(tree)
  149.       {while(*(++p4)){*p4+=*p3++ +tmov;if(*p4<tmov) *p4+=14;} p4+=44;}
  150.     else
  151.       {while(*(++p4)){*p4+=tmov;if(*p4<tmov) *p4+=14;} p4+=44;}
  152.   }
  153. }
  154. draw_word(int xx, int yy, char *cc, int boris)
  155. {
  156.    BITMAP *letter; int v, w, y, z;
  157.    z = strlen(cc);
  158.    letter = create_bitmap(z*20,16);
  159.    clear(letter);
  160.    for(w=0; w<z;w++) {
  161.       v = *cc++ - 97;                    
  162.       if(v >= 0 && v < 26) y = 1;
  163.       else {v += 49;y=19;}
  164.       if(v >= 0 && v < 26) 
  165.       blit(datafile[FONT].dat, letter, v*17+1, y, w*20, 0, 16, 16);
  166.    }
  167.    for(v=0;v<16;v++) {
  168.       for(w=0;w<(z*20);w++)
  169.          if(boris) letter->line[v][w] = getpixel(letter, w, v) ? (xx+w+v)%242+14 : 0;
  170.          else letter->line[v][w] = getpixel(letter, w, v);
  171.    }
  172.    screen->vtable->blit_from_memory(letter, screen, 0, 0, xx, yy, z*20, 16);
  173.    if(boris==2) screen->vtable->blit_from_memory(letter, tempa, 0, 0, xx, yy, z*20, 16);
  174.    destroy_bitmap(letter);
  175. }
  176. init()
  177. {
  178.    int x, z; RGB rgbt[498];
  179.    unsigned char *pa, *pb, mtemp[1024];
  180.    x = time(0); srandom(x);
  181.    allegro_init(); install_keyboard(); install_timer(); open_file();
  182.    if(songpos != 2)
  183.       if (install_sound(DIGI_NONE, MIDI_AUTODETECT, NULL) != 0) songpos = 2;
  184.    datafile = load_datafile("card.dat");
  185.    if(!datafile){allegro_exit();printf("Error loading card.dat\n\n");exit(1);}
  186.    strcpy(mtemp,message); pa=message; pb = mtemp;
  187.    for(x=0;x<19;x++) *pa++=255;
  188.    while(*pb) {
  189.       if(*pb > 47 && *pb < 65) *pa = *pb-22;
  190.       else if(*pb > 96 && *pb < 123) *pa = *pb-97;
  191.       else if(*pb > 64 && *pb < 91) *pa = *pb-65;
  192.       else *pa = 255;
  193.       if (*pb==33) *pa=38;
  194.       if (*pb==46) *pa=39;
  195.       if (*pb==44) *pa=40;
  196.       if (*pb>38 && *pb < 42) *pa=*pb+2;
  197.       if (*pb==45) *pa=44;
  198.       if (*pb==63) *pa=45;
  199.       *pa++; *pb++;
  200.    }
  201.    for(x=0;x<24;x++) *pa++=255; *pa=128;
  202.    if(songpos != 2) {
  203.       if(songpos == 0) play_midi(datafile[SONG1].dat, TRUE);
  204.       else if(songpos == 1) play_midi(datafile[SONG2].dat, TRUE);
  205.       else {
  206.          the_song = load_midi(song_name);
  207.          if(play_midi(the_song, TRUE) || !the_song) {
  208.             allegro_exit();
  209.             printf("Error loading %s\n\n",song_name);
  210.             exit(1);
  211.          }
  212.       }
  213.    }
  214.    set_gfx_mode(GFX_MODEX, 360, 360, 0, 0);
  215.    set_pallete_range(datafile[PALLETE_001].dat, 0, 255, 1); get_pallete(rgbt);
  216.    set_pallete_range(black_pallete, 1, 255, 1); x=random()%2;
  217.    if(picpos == 2) {
  218.       if(!x) screen->vtable->blit_from_memory(datafile[BOY].dat, screen, 0, 0, 40, 40, 280, 280);
  219.       else screen->vtable->blit_from_memory(datafile[ANGEL].dat, screen, 0, 0, 40, 40, 280, 280);
  220.    }
  221.    else {
  222.       if (!picpos) screen->vtable->blit_from_memory(datafile[BOY].dat, screen, 0, 0, 40, 40, 280, 280);
  223.       else if (picpos == 1) screen->vtable->blit_from_memory(datafile[ANGEL].dat, screen, 0, 0, 40, 40, 280, 280);
  224.       else {
  225.          intro_pic = load_pcx(pic_name,picpal);
  226.          if (intro_pic->w<360) x=intro_pic->w; else x=360;
  227.          if (intro_pic->h<360) z=intro_pic->h; else z=360;
  228.          screen->vtable->blit_from_memory(intro_pic, screen, 0, 0, (360-x)/2, (360-z)/2, x, z);
  229.       }
  230.    }
  231.    if(picpos == 3) fade_in(picpal, 2);
  232.    else fade_in(datafile[PALLETE_002].dat, 2);
  233.    destroy_bitmap(datafile[BOY].dat); destroy_bitmap(datafile[ANGEL].dat);
  234.    for(z=0;z<242;z++) rgbt[z+256]=rgbt[z+14];
  235.    transparence = create_bitmap(443,37);
  236.    tempa = create_bitmap(16, 16); treepic = create_bitmap(20, 20);
  237.    if(textpos) blit(datafile[FONTT].dat, transparence, 0, 0, 0, 0, 443, 37);
  238.    else blit(datafile[FONT].dat, transparence, 0, 0, 0, 0, 443, 37);
  239.    for(x=0;x<280;x++) {
  240.       temptbl[x] = 1;
  241.       if(x<242) {
  242.          memcpy(&pal[x][0],&rgbt[0],56);
  243.          memcpy(&pal[x][14],&rgbt[x+14],968);
  244.       }
  245.       if(x<100) {xpos[x] = random()%320;col[x] = random()%6+7;}
  246.       if(x<46) {
  247.          if(x<26) blit(transparence, tempa, x*17+1, 1, 0, 0, 16, 16);
  248.          else blit(transparence, tempa, (x-26)*17+1, 19, 0, 0, 16, 16);
  249.          for(z=0;z<42;z++) {
  250.             clear(treepic);
  251.             rotate_sprite(treepic,tempa,2,2,itofix(sintbl[z]));
  252.             rot[x][z]=get_compiled_sprite(treepic, 0);
  253.          }
  254.       }
  255.    }
  256.    destroy_bitmap(transparence);destroy_bitmap(tempa);
  257.    destroy_bitmap(treepic);destroy_bitmap(datafile[FONTT].dat);temptbl[280]=0;
  258.    if(!textpos) set_clip(buffer,0,0,0,0);else set_clip(buffer,20,5,300,130);
  259.    fade_out(2);
  260.    set_gfx_mode(GFX_VGA, 320, 200, 0, 0);
  261.    set_pallete_range(black_pallete, 1, 255, 1);
  262.    treepic = create_bitmap(280,125);tempa=create_bitmap(320,200);
  263.    if(bgpos) {
  264.       tree = 1;
  265.       if(bgpos == 1) screen->vtable->blit_from_memory(datafile[TREE].dat, treepic, 0, 0, 0, 0, 280, 125);
  266.       else screen->vtable->blit_from_memory(datafile[CROSS].dat, treepic, 0, 0, 0, 0, 280, 125);
  267.    }
  268.    else screen->vtable->blit_from_memory(datafile[TREE].dat, treepic, 0, 0, 0, 0, 280, 125);
  269.    drawplasma();
  270.    draw_word(10,20, "merry christmas",1);
  271.    screen->vtable->blit_from_memory(buffer, screen, 20, 5, 20, 60, 280, 125);
  272.    screen->vtable->blit_from_memory(screen, tempa, 0, 0, 0, 0, 320, 200);
  273.    fade_in(datafile[PALLETE_001].dat, 2);
  274.    install_int(game_timer, 250);
  275. }
  276. setup_mode()
  277. {
  278.    struct text_info i; int x,y;unsigned int keyp; char buff[5000];FILE *fp;
  279.    open_file(); gettextinfo(&i); gettext(1,1,80,25,buff);
  280.    allegro_init(); install_keyboard(); textmode(C80); system("funfont.com");
  281.    _setcursortype(_NOCURSOR);
  282.    textattr (RED*16 | 15);
  283.    gotoxy(1,1); cprintf(" Christmas Card v1.5 Setup - This program is freeware created by Michael Bevin  ");
  284.    textattr (BLUE*16 | 15);
  285.    gotoxy(0,23);cprintf("  Press <F10> to quit and save, <Esc> to quit without saving                     ");
  286.    textattr (LIGHTGRAY*16 | LIGHTBLUE);
  287.    fill_text_screen();
  288.    gotoxy(5,5); cprintf("Boy & santa claus");
  289.    gotoxy(5,6); cprintf("Angel with wings");
  290.    gotoxy(5,7); cprintf("Randomly either");
  291.    gotoxy(25,5);cprintf("Danish carols");
  292.    gotoxy(25,6);cprintf("Away in a manger");
  293.    gotoxy(25,7);cprintf("Music disabled");
  294.    gotoxy(45,5);cprintf("Normal");
  295.    gotoxy(45,6);cprintf("Transparent");
  296.    gotoxy(58,5);cprintf("None at start");
  297.    gotoxy(58,6);cprintf("Christmas tree");
  298.    gotoxy(58,7);cprintf("Cross");
  299.    textattr (LIGHTGRAY*16 | LIGHTMAGENTA);
  300.    draw_text_line(4, 10, 72);
  301.    textattr (LIGHTGRAY*16 | LIGHTRED);
  302.    gotoxy(4,picpos+5);cprintf("%c",4);
  303.    gotoxy(24,songpos+5);cprintf("%c",4);
  304.    gotoxy(44,textpos+5);cprintf("%c",4);
  305.    gotoxy(57,bgpos+5);cprintf("%c",4);
  306.    textattr (LIGHTGRAY*16 | MAGENTA);
  307.    draw_text_line(4, 23, 72);
  308.    textattr (LIGHTGRAY*16 | 14);
  309.    gotoxy(5,3);  cprintf("Intro Picture");
  310.    gotoxy(25,3); cprintf("Song (.MID)  ");
  311.    gotoxy(45,3); cprintf("Text Style");
  312.    gotoxy(58,3); cprintf("Plasma Background");
  313.    show_song_name();
  314.    show_pic_name();
  315.    show_message();
  316.    dots=1;
  317.    gotoxy(5,11);
  318.    while(!key[KEY_ESC] && !key[KEY_F10]) {
  319.       if(keypressed() && !key[KEY_ESC]) {
  320.          keyp=readkey();
  321.          if(keyp >> 8 == KEY_UP) {
  322.             textattr (LIGHTGRAY*16 | LIGHTRED);
  323.             switch(s_pos) {
  324.             case 1:
  325.                gotoxy(4,picpos+5);cprintf(" ");
  326.                picpos--;if(picpos < 0) picpos = 3;
  327.                gotoxy(4,picpos+5);cprintf("%c",4);
  328.                break;
  329.             case 2:
  330.                gotoxy(24,songpos+5);cprintf(" ");
  331.                songpos--;if(songpos < 0) songpos = 3;
  332.                gotoxy(24,songpos+5);cprintf("%c",4);
  333.                break;
  334.             case 3:
  335.                gotoxy(44,textpos+5);cprintf(" ");
  336.                textpos--;if(textpos < 0) textpos = 1;
  337.                gotoxy(44,textpos+5);cprintf("%c",4);
  338.                break;
  339.             case 4:
  340.                gotoxy(57,bgpos+5);cprintf(" ");
  341.                bgpos--;if(bgpos < 0) bgpos = 2;
  342.                gotoxy(57,bgpos+5);cprintf("%c",4);
  343.                break;
  344.             default:
  345.                s_row--;
  346.                if(s_row<0) s_row=0;
  347.                if(s_col>=(offsets[s_row+1]-offsets[s_row])) s_col = offsets[s_row+1]-offsets[s_row]-1;
  348.             }
  349.             show_pos();
  350.          }
  351.          if(keyp >> 8 == KEY_DOWN) {
  352.             textattr (LIGHTGRAY*16 | LIGHTRED);
  353.             switch(s_pos) {
  354.             case 1:
  355.                gotoxy(4,picpos+5);cprintf(" ");
  356.                picpos++;if(picpos > 3) picpos = 0;
  357.                gotoxy(4,picpos+5);cprintf("%c",4);
  358.                break;
  359.             case 2:
  360.                gotoxy(24,songpos+5);cprintf(" ");
  361.                songpos++;if(songpos > 3) songpos = 0;
  362.                gotoxy(24,songpos+5);cprintf("%c",4);
  363.                break;
  364.             case 3:
  365.                gotoxy(44,textpos+5);cprintf(" ");
  366.                textpos++;if(textpos > 1) textpos = 0;
  367.                gotoxy(44,textpos+5);cprintf("%c",4);
  368.                break;
  369.             case 4:
  370.                gotoxy(57,bgpos+5);cprintf(" ");
  371.                bgpos++;if(bgpos > 2) bgpos = 0;
  372.                gotoxy(57,bgpos+5);cprintf("%c",4);
  373.                break;
  374.             default:
  375.                s_row++;
  376.                if(s_row>s_rows) s_row=s_rows;
  377.                if(s_row > 11) s_row = 11;
  378.                if(s_col>=(offsets[s_row+1]-offsets[s_row])) s_col = offsets[s_row+1]-offsets[s_row]-1;
  379.             }
  380.             show_pos();
  381.          }
  382.          if(keyp >> 8 == KEY_LEFT) {
  383.             if(s_pos == 5) {
  384.                s_col--;
  385.                if(s_col<0 && s_row>0) {
  386.                   s_row--;
  387.                   s_col = offsets[s_row+1]-offsets[s_row]-1;
  388.                }
  389.                if(s_col<0) s_col = 0;
  390.             }
  391.             else if(s_pos == 1 && picpos == 3) {
  392.                p_col--;
  393.                if(p_col<0) p_col = 0;
  394.             }
  395.             else if(s_pos == 2 && songpos == 3) {
  396.                m_col--;
  397.                if(m_col<0) m_col = 0;
  398.             }
  399.             else {
  400.                s_pos--;if(s_pos<0) s_pos=5;
  401.             }
  402.             show_pos();
  403.          }
  404.          if(keyp >> 8 == KEY_END) {
  405.             if(s_pos == 5) s_col=offsets[s_row+1]-offsets[s_row]-1;
  406.             else if(s_pos == 1 && picpos == 3) p_col=strlen(pic_name);
  407.             else if(s_pos == 2 && songpos == 3) m_col=strlen(song_name);
  408.             show_pos();
  409.          }
  410.          if(keyp >> 8 == KEY_HOME) {
  411.             if(s_pos == 5) s_col=0;
  412.             else if(s_pos == 1 && picpos == 3) p_col=0;
  413.             else if(s_pos == 2 && songpos == 3) m_col=0;
  414.             show_pos();
  415.          }
  416.          if(keyp >> 8 == KEY_DEL) {
  417.             _setcursortype(_NOCURSOR);
  418.             if(s_pos == 5) {
  419.                x = offsets[s_row]+s_col;
  420.                delete_chara(message, offsets[s_row]+s_col);
  421.                show_message();
  422.                if(s_col > offsets[s_row+1]-offsets[s_row]-1 && s_row<11) {
  423.                   s_row++;
  424.                   s_col = x - offsets[s_row];
  425.                }
  426.                else if(s_col+offsets[s_row] > x && s_row) {
  427.                   s_row--;
  428.                   s_col = x - offsets[s_row];
  429.                }
  430.             }
  431.             else if(s_pos==1 && picpos == 3) {
  432.                delete_chara(pic_name, p_col);
  433.                show_pic_name();
  434.             }
  435.             else if(s_pos==2 && songpos == 3) {
  436.                _setcursortype(_NOCURSOR);
  437.                delete_chara(song_name, m_col);
  438.                show_song_name();
  439.             }
  440.             show_pos();
  441.             _setcursortype(_NORMALCURSOR);
  442.          }
  443.          if(keyp >> 8 == KEY_BACKSPACE) {
  444.             if(s_pos == 5) {
  445.                s_col--;
  446.                if(s_col<0 && !s_row) s_col = 0;
  447.                else {
  448.                   x = offsets[s_row]+s_col;
  449.                   delete_chara(message, offsets[s_row]+s_col);
  450.                   show_message();
  451.                   if(x != offsets[s_row]+s_col || s_col < 0) {
  452.                      if(x >= offsets[s_row]) s_col = x - offsets[s_row];
  453.                      else {
  454.                         s_row--;
  455.                         s_col = x - offsets[s_row];
  456.                      }
  457.                   }
  458.                   show_pos();
  459.                }
  460.             }
  461.             else if(s_pos == 1 && picpos == 3) {
  462.                p_col--;
  463.                if(p_col<0) p_col=0;
  464.                else {
  465.                   delete_chara(pic_name, p_col);
  466.                   show_pic_name();
  467.                   show_pos();
  468.                }
  469.             }
  470.             else if(s_pos == 2 && songpos == 3) {
  471.                m_col--;
  472.                if(m_col<0) m_col=0;
  473.                else {
  474.                   delete_chara(song_name, m_col);
  475.                   show_song_name();
  476.                   show_pos();
  477.                }
  478.             }
  479.          }
  480.          if((keyp & 0xff) == 25) {
  481.             for(x=offsets[s_row];x<920;x++)
  482.                message[x]=message[x+offsets[s_row+1]-offsets[s_row]];
  483.             if(s_row >= s_rows) {
  484.                if(s_row) {
  485.                   s_row--;
  486.                   s_col=offsets[s_row+1]-offsets[s_row]-1;
  487.                   message[s_col+offsets[s_row]] = 0;
  488.                }
  489.                else {
  490.                   s_col=0;
  491.                   message[0]=0;
  492.                }
  493.             }
  494.             show_message();
  495.             show_pos();
  496.          }
  497.          else if(((keyp & 0xff) > 19) && ((keyp & 0xff) < 124) && s_pos == 5
  498.          && (s_row<11 || s_col<69)) {
  499.             x = offsets[s_row]+s_col;
  500.             insert_chara(message, offsets[s_row]+s_col, keyp & 0xff);
  501.             show_message();
  502.             s_col++;
  503.             if(s_col>=(offsets[s_row+1]-offsets[s_row]) && s_row<s_rows && s_row<11) {
  504.                s_row++;
  505.                s_col = x+1-offsets[s_row];
  506.             }
  507.             else if(x+1 < s_col+offsets[s_row]) s_col = 0;
  508.             if(s_col>=(offsets[s_row+1]-offsets[s_row])) s_col = offsets[s_row+1]-offsets[s_row]-1;
  509.             show_pos();
  510.          }
  511.          if(((keyp & 0xff) > 19) && ((keyp & 0xff) < 124) && s_pos == 1 && picpos == 3) {
  512.             _setcursortype(_NOCURSOR);
  513.             insert_chara(pic_name, p_col, keyp & 0xff);
  514.             if(p_col<15) p_col++;
  515.             show_pic_name();
  516.             show_pos();
  517.             _setcursortype(_NORMALCURSOR);
  518.          }
  519.          if(((keyp & 0xff) > 19) && ((keyp & 0xff) < 124) && s_pos == 2 && songpos == 3) {
  520.             _setcursortype(_NOCURSOR);
  521.             insert_chara(song_name, m_col, keyp & 0xff);
  522.             if(m_col<15) m_col++;
  523.             show_song_name();
  524.             show_pos();
  525.             _setcursortype(_NORMALCURSOR);
  526.          }
  527.          if(keyp >> 8 == KEY_RIGHT) {
  528.             if(s_pos == 5) {
  529.                s_col++;
  530.                if(s_col>=(offsets[s_row+1]-offsets[s_row]) && s_row<s_rows && s_row<11) {
  531.                   s_row++;
  532.                   s_col = 0;
  533.                }
  534.                if(s_col>=(offsets[s_row+1]-offsets[s_row])) s_col = offsets[s_row+1]-offsets[s_row]-1;
  535.             }
  536.             else if(s_pos == 1 && picpos == 3) {
  537.                p_col++;
  538.                if(p_col>strlen(pic_name)) p_col = strlen(pic_name);
  539.             }
  540.             else if(s_pos == 2 && songpos == 3) {
  541.                m_col++;
  542.                if(m_col>strlen(song_name)) m_col = strlen(song_name);
  543.             }
  544.             else {
  545.                s_pos++;if(s_pos>5) s_pos=0;
  546.             }
  547.             show_pos();
  548.          }
  549.          if(keyp >> 8 == KEY_TAB) {
  550.             if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) {
  551.                s_pos--;
  552.                if(!s_pos) s_pos = 5;
  553.             }
  554.             else {
  555.                s_pos++;
  556.                if(s_pos > 5) s_pos = 1;
  557.             }
  558.             show_pos();
  559.          }
  560.       }
  561.    }
  562.    if(key[KEY_F10]) {
  563.       if((fp = fopen("card.cfg","wb"))) {
  564.          fwrite(message,1024,1,fp);
  565.          fwrite(song_name,15,1,fp);
  566.          fwrite(pic_name,15,1,fp);
  567.          putc(songpos,fp);
  568.          putc(picpos,fp);
  569.          putc(bgpos,fp);
  570.          putc(textpos,fp);
  571.          fclose(fp);
  572.       }
  573.    }
  574.    allegro_exit();
  575.    if(!font_change) textmode(C80);
  576.    puttext(1,1,80,25,buff);
  577.    gotoxy(i.curx,i.cury);
  578.    textattr(i.attribute);
  579.    exit(1);
  580. }
  581. show_pos()
  582. {
  583.    switch(s_pos) {
  584.    case 1:
  585.       if(picpos < 3) gotoxy(4,picpos+5);
  586.       else gotoxy(6+p_col,8);
  587.       break;
  588.    case 2:
  589.       if(songpos < 3) gotoxy(24,songpos+5);
  590.       else gotoxy(26+m_col,8);
  591.       break;
  592.    case 3:
  593.       gotoxy(44,textpos+5);
  594.       break;
  595.    case 4:
  596.       gotoxy(57,bgpos+5);
  597.       break;
  598.    default:
  599.       gotoxy(s_col+5,s_row+11);
  600.    }
  601. }
  602. show_message()
  603. {
  604.    int x,y,end_mes=0, not_full=0;
  605.    unsigned char temp_mes[71],*pm;
  606.    offsets[0]=0; _setcursortype(_NOCURSOR); 
  607.    x=s_row-1; if(x<0) x=0;
  608.    for(y=x;y<13;y++) {
  609.       pm=message+offsets[y];
  610.       strncpy(temp_mes,pm,70);
  611.       textattr (0 | LIGHTGRAY);
  612.       x=70;
  613.       while(x) {
  614.          x--;
  615.          if(temp_mes[x] == 32) not_full = 1;
  616.          if(!end_mes && temp_mes[x] == 32) {offsets[y+1] = offsets[y]+x+1; x=0;}
  617.          if(!end_mes && temp_mes[x] == 0) end_mes=1;
  618.          if(end_mes && temp_mes[x]>0) {offsets[y+1] = offsets[y]+x+2;x=0;}
  619.          if(x) temp_mes[x]=0;
  620.       }
  621.       if(!not_full && !end_mes) {
  622.          offsets[y+1] = offsets[y]+69;
  623.          strncpy(temp_mes,pm,70);
  624.       }
  625.       if(message[offsets[y]]==0) temp_mes[0]=0;
  626.       if(offsets[y+1]<=offsets[y]) offsets[y+1] = offsets[y];
  627.       temp_mes[70]=0;
  628.       if(y<12) {
  629.          gotoxy(5,y+11);
  630.          cprintf("%s",temp_mes);
  631.       }
  632.       textattr (0 | DARKGRAY);
  633.       not_full = strlen(temp_mes);
  634.       for(x=not_full;x<70;x++) cprintf("·");
  635.       if(end_mes) {
  636.          s_rows=y;
  637.          y++;
  638.          if(y<12) {
  639.             gotoxy(5,y+11);
  640.             cprintf("······································································");
  641.          }
  642.          if(!dots) {
  643.             while(y<11) {
  644.                gotoxy(5,++y+11);
  645.                cprintf("······································································");
  646.             }
  647.          }
  648.          _setcursortype(_NORMALCURSOR);
  649.          return(1);
  650.       }
  651.    }
  652.    s_rows=y;
  653.    _setcursortype(_NORMALCURSOR);
  654. }
  655. draw_text_line(int x, int y, int length)
  656. {
  657.    int z;
  658.    gotoxy(x,y); cprintf("■");
  659.    gotoxy(x+1,y);
  660.    for (z=x+1;z<x+length-1;z++) cprintf("─");
  661.    gotoxy(x+length-1,y); cprintf("■");
  662. }
  663. fill_text_screen()
  664. {
  665.    int x,y;
  666.    for(y=2;y<24;y++) {
  667.          gotoxy(1,y);
  668.          cprintf("                                                                                ");
  669.    }
  670. }
  671. open_file()
  672. {
  673.    FILE *fp;
  674.    if((fp = fopen("card.cfg","rb"))) {
  675.       fread(message,1024,1,fp);fread(song_name,15,1,fp);fread(pic_name,15,1,fp);
  676.       songpos = getc(fp);picpos = getc(fp);bgpos = getc(fp);textpos = getc(fp);
  677.       fclose(fp);
  678.    }
  679.    else {
  680.       strcpy(message,"Merry christmas and a happy new year to all u computer users out there. This program is freeware and u may give it 2 your friends as an 'electronic christmas card' by editing this message (type card -s at command prompt)... The intro screen is a modex resolution at 360 by 360 so most pictures will b a bit squewed, but u can use pictures of any size and it should work ::: thanx to dj delorie for making djgpp, shawn hargreaves for the allegro game programming library, and christopher norton whose christmas carol music i stole ::: please write to me at michael.bevin at stonebow.otago.ac.nz if u like this or otherwise... and take some time out to remember what christmas is all about!!    :");
  681.       strcpy(song_name,"<songname.mid>");
  682.       strcpy(pic_name,"<picname.pcx>");
  683.    }
  684. }
  685. show_pic_name()
  686. {
  687.       pic_name[15]=0;
  688.       textattr (0 | DARKGRAY);
  689.       gotoxy(5,8); cprintf(">···············<");
  690.       textattr (0 | LIGHTGRAY);
  691.       gotoxy(6,8); cprintf("%s",pic_name);
  692. }
  693. show_song_name()
  694. {
  695.       song_name[15]=0;
  696.       textattr (0 | DARKGRAY);
  697.       gotoxy(25,8); cprintf(">···············<");
  698.       textattr (0 | LIGHTGRAY);
  699.       gotoxy(26,8); cprintf("%s",song_name);
  700. }
  701.